package com.lemurian.bankdata.bean;

import java.sql.Timestamp;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.springframework.stereotype.Repository;

import com.lemurian.bankdata.bean.base.BaseDaoHibernate;
import com.lemurian.bankdata.dto.LogHelper;
import com.lemurian.bankdata.lite.enums.UserActivityType;
import com.lemurian.bankdata.lite.logger.BankDataLogger;
import com.lemurian.bankdata.lite.struts.PartialList;
import com.lemurian.bankdata.lite.utils.BankDataCommons;
import com.lemurian.entity.ActivityLog;
import com.lemurian.entity.ActivityTypes;

@Repository
public class ActivityLogDAO extends BaseDaoHibernate<ActivityLog>{
	
	private BankDataLogger log = BankDataLogger.getLogger(ActivityLogDAO.class.getName());
	
	@Override
	public PartialList<ActivityLog> findByCriteria(int start, int count, Order order, Criterion... criterion){
		PartialList<ActivityLog> partialList = null;
		try {
			// total
			Criteria criteria = getSession().createCriteria(ActivityLog.class).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
			
			criteria.setCacheable(true);
			
			criteria.setFetchMode("activityTypes", FetchMode.JOIN);
			
			for (Criterion c : criterion) {
				criteria.add(c);
			}
			criteria.setProjection(Projections.rowCount());
			int total = ((Integer) criteria.list().iterator().next()).intValue();
			
			// partial data
			criteria = getSession().createCriteria(ActivityLog.class).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
			criteria.setCacheable(true);
			
			criteria.setFetchMode("activityTypes", FetchMode.JOIN);
			
			for (Criterion c : criterion) {
				criteria.add(c);
			}

			if (order!=null) criteria.addOrder(order);
			criteria.setFirstResult(start);
			criteria.setMaxResults(count);
			
			partialList = new PartialList<ActivityLog>(criteria.list(), total);
		} catch(Exception exception){
			getSession().getTransaction().rollback();
		}
		return partialList;
	}
	
	public void saveUserActivity(LogHelper actHelper) {
        try {
            //set the date here for temporary logic. 
            Date now = new Date();
            ActivityLog actLog = new ActivityLog();

            //set user
            actLog.setLoginId(actHelper.getUser().getLoginId());

            //set another information
            actLog.setStatus(actHelper.getStatus());
            actLog.setStartTime(actHelper.getStartDate());
            actLog.setEndTime(actHelper.getEndDate());
            actLog.setSessionId(actHelper.getSessionId());
            actLog.setErrorMsg(actHelper.getErrorMsg());
            actLog.setErrorCode(actHelper.getErrorCode());
            actLog.setCreateDate(new Timestamp(System.currentTimeMillis()));
            actLog.setCreateBy(actHelper.getUser().getName());
            
            log.sInfo(" :: [BANK_DATA_ACTIVITY_LOG] start time : %s", actHelper.getStartDate());
            log.sInfo(" :: [BANK_DATA_ACTIVITY_LOG] end time : %s", actHelper.getEndDate());

            if(actHelper.getStartDate() == null) {
            	actHelper.setStartDate(new Date());
            }
            
            if(actHelper.getEndDate() == null) {
            	actHelper.setEndDate(new Date());
            }
            
            //determine activity type
            ActivityTypes type = (ActivityTypes) getSession().get(ActivityTypes.class, actHelper.getType().code());
            if (type == null) {
                type = new ActivityTypes(UserActivityType.UNKNOWN.code());
            }
            actLog.setActivityTypes(type);

            //fill remarks
            if (actHelper.getRemarks() == null || actHelper.getRemarks().equals("")) {
                String remarks = "";
                // Do check of spesific activity types here according to remarks format in properties file

                //ex format in properties :
                //  User with login id %s is login into system
                List<Object> temp = new ArrayList<Object>();
                temp.add(actHelper.getUser().getLoginId());
                for (Object o : actHelper.getAdditionalParams()) {
                    temp.add(o);
                }
                remarks = MessageFormat.format(BankDataCommons.getBankDataActivityLogConfig().getString(actHelper.getType().name()), temp.toArray());
                actHelper.setRemarks(remarks);
            }
            actLog.setRemarks(actHelper.getRemarks());

            log.sInfo(" :: [BANK_DATA_ACTIVITY_LOG] %s", actLog.getRemarks());
            //persist log
            save(actLog);

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
